package study.thread.semaphore;

import java.util.concurrent.Semaphore;
/**
 * 下面的类使用信号量控制对内容池的访问，内容池的大小作为 Semaphore 的构造
 * 参数传递初始化许可的数目，每个线程获取数据之前必须获得许可，这样就限制了访问内容
 * 池的线程数目.
 * @author hawk
 *
 */
class PoolSemaphoreDemo {
	
	private static final int MAX_AVAILABLE = 5;
	
	private final Semaphore available = new Semaphore(MAX_AVAILABLE, true);
	
	protected Object[] items = { "AAA", "BBB", "CCC", "DDD", "EEE" };
	protected boolean[] used = new boolean[MAX_AVAILABLE];//数组中的元素默认初始化为false
	
	//获取数据，需要得到许可 
	public Object getItem() throws InterruptedException {
		available.acquire();
		return getNextAvailableItem();
	}
	
	public static void main(String args[]) {
		
		final PoolSemaphoreDemo pool = new PoolSemaphoreDemo();
		//System.out.println(pool.used[2]);
		Runnable runner = new Runnable() {
			public void run() {
				try {
					Object o;
					o = pool.getItem();//拿第i个元素item[i]，同时将used[i]标记为true
					System.out.println(Thread.currentThread().getName()
							+ " acquire " + o);
					Thread.sleep(1000);
					pool.putItem(o);
					System.out.println(Thread.currentThread().getName()
							+ " release " + o);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		};
		for (int i = 0; i < 10; i++)// 构造 10 个线程 
		{
			Thread t = new Thread(runner, "t" + i);
			t.start();
		}
	}

	//放回数据，释放许可 
	public void putItem(Object x) {
		if (markAsUnused(x))
			available.release();
	}

	protected synchronized Object getNextAvailableItem() {
		for (int i = 0; i < MAX_AVAILABLE; ++i) {
			if (!used[i]) {
				used[i] = true;
				return items[i];
			}
		}
		return null;
	}

	protected synchronized boolean markAsUnused(Object item) {
		for (int i = 0; i < MAX_AVAILABLE; ++i) {
			if (item == items[i]) {
				if (used[i]) {
					used[i] = false;
					return true;//放回操作成功，释放资源
				} else
					return false;
			}
		}
		return false;
	}
}
